
/**
  * ******************************************************************************
  * @file           : power_control.c/h
  * @brief          : 超级电容的功率控制
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022  11/12 颜福兵.
  * All rights reserved.
  *
  **/

#include "power_control.h"


int8_t key0=0;
int8_t key1=0;


 sample_t sample;                   //采样结构体
 power_control_t power_control;     //控制结构体
 status_t status;                   //状态结构体

 uint32_t time=0;       //获取运算一次的时间
 uint32_t dead_time = 0;
 
 /**
  * @brief 电容充放电闭环控制
  * @param  无
  */
 static void control_calc(sample_t* samples,power_control_t* powercontrols,status_t *states);
 
 /**
  * @brief 计算并更新buckboost电路的PWM
  * @param volt_ratio 
  */
 static void buckboost_pwm_update(float volt_ratio);
 
 uint16_t count = 0;
 
 /**
  * @brief          定时器中断回调函数
  * @param[in]      htim: 定时器句柄
  * @retval         无
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) {
    if (htim == &htim7) {    //周期100us
        time = micros();
        control_calc(&sample, &power_control, &status);  //大概运算55us
        dead_time = micros() - time;

        if (count++ > 1000) {
            count = 0;
           // HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
            HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
            //	HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
        }
    }
}
 
 /**
  * @brief 电容充放电的闭环控制
  * @param no
  */
CCMRAM static void control_calc(sample_t* samples, power_control_t* powercontrols, status_t* states) {
    static uint16_t adc1_buf[3];
    static uint16_t adc2_buf[2];
    Get_ADC_Value(&hadc1, adc1_buf);   //电流采集adc1
    Get_ADC_Value(&hadc2, adc2_buf);   //电压采集ADC2
    for (uint8_t i = 0;i < 3;i++) {
        samples->adc1_buf[i] = adc1_buf[i];
        if (i < 3) {
            samples->adc2_buf[i] = adc2_buf[i];
        }
    }

    ADC_Value_To_Elec(&samples->in_v_filter, (uint16_t)samples->adc2_buf[1]);
    ADC_Value_To_Elec(&samples->out_c_filter, (uint16_t)samples->adc1_buf[0]);
    ADC_Value_To_Elec(&samples->in_c_filter, (uint16_t)samples->adc1_buf[2]);
    ADC_Value_To_Elec(&samples->cap_c_filter, (uint16_t)samples->adc1_buf[1]);
    ADC_Value_To_Elec(&samples->cap_v_filter, (uint16_t)samples->adc2_buf[0]);

    samples->in_v = samples->in_v_filter.output;        //输入电压直接测得
    samples->in_c = samples->in_c_filter.output;        //输入的电流直接测得
    samples->in_p = samples->in_v * samples->in_c;      //计算得到输入的功率
 	
    samples->out_v = samples->in_v_filter.output;       //输出电压与输入电压一致
    samples->out_c = samples->out_c_filter.output;      //输出的电流直接测得
    samples->out_p = samples->out_v * samples->out_c;   //计算输出的功率

    samples->dcdc_v = samples->in_v_filter.output;      //dcdc输入的电压与输出的电压一致
    samples->dcdc_c = samples->in_c - samples->out_c;
    samples->dcdc_p = samples->dcdc_c * samples->dcdc_v;

    samples->cap_v = samples->cap_v_filter.output;
    samples->cap_c = samples->in_c - samples->out_c;
    samples->cap_p = samples->cap_v * samples->cap_c;   //计算得到电容的功率
    //外环功率环, 得到dcdc充放电功率
    powercontrols->dcdc_power = PID_calc(&powercontrols->powerin_loop, samples->in_p, powercontrols->power_set+key0);
    //计算并限制最大dcdc充放电电流
    powercontrols->dcdc_curr = fmaxf(fminf((powercontrols->dcdc_power) / samples->dcdc_v, 5/*powercontrols->dcdc_max_curr*/), -5/*powercontrols->dcdc_max_curr*/);
    //判断充放电
    if (powercontrols->dcdc_power >= 0.0f) {
        //充电
        states->capmode = CAP_CHARGE;
        //电压电流环并行计算
        powercontrols->cloop_ratio = PID_calc(&powercontrols->currout_loop, samples->dcdc_c, powercontrols->dcdc_curr) / samples->dcdc_v;
        powercontrols->vloop_ratio = PID_calc(&powercontrols->voltout_loop, samples->cap_v , powercontrols->cap_v_max) / samples->dcdc_v;

        if (powercontrols->vloop_ratio <= powercontrols->cloop_ratio) {
            //恒压
            powercontrols->volt_ratio = powercontrols->vloop_ratio;
            states->control_mode = CONTROL_CV;
        }
        else {
            //恒流
           powercontrols->volt_ratio = powercontrols->cloop_ratio;
            states->control_mode = CONTROL_CC;
        }
        //更新PWM
        buckboost_pwm_update(powercontrols->volt_ratio);
    }
    else if (powercontrols->dcdc_power < 0) {
        //放电
        states->capmode = CAP_DISCHARGE;
        states->control_mode = CONTROL_CC;
        //单电流环PID
        powercontrols->cloop_ratio = PID_calc(&powercontrols->currout_loop, samples->dcdc_c, powercontrols->dcdc_curr) / samples->cap_v;
        powercontrols->volt_ratio = powercontrols->cloop_ratio;
        //更新PWM
        buckboost_pwm_update(powercontrols->volt_ratio);
    }
		
}

/**
  * @brief          计算并更新buckboost的pwm
  * @param[in,out]  volt_ratio: 电压比值 (Vout/Vin)
  * @retval         无
  */
   /*
    * 升降压的PWM方案：
    * 1.由于MOS采用自举电容驱动方式，故上管不能100%占空比导通，这里我们设为95%。
    * 2.本函数的输入参数为总的占空比，需要分别算出两个半桥的占空比。
    * 3.降压工作时，BOOST的半桥的占空比是固定的为95%，通过改变BUCK半桥占空比实现稳压。
    * 3.升压或等压工作时，BUCK半桥的占空比是固定的为95%，通过改变BOOST半桥占空比实现稳压。
    */
 
CCMRAM static void buckboost_pwm_update(float volt_ratio) {
 volatile unsigned int CompareValue;
 volatile unsigned int buck_duty;
 volatile unsigned int boost_duty;
    volt_ratio = fminf(MAX_VOLT_RATIO, volt_ratio);
    volt_ratio = fmaxf(MIN_VOLT_RATIO, volt_ratio);

    if (volt_ratio >= 1.0f) {
        CompareValue = DP_PWM_PER * (MAX_DUTY2 - MAX_DUTY / volt_ratio);
    }
    else {
        CompareValue = MAX_DUTY * volt_ratio * DP_PWM_PER;
    }
    //计算boost半桥占空比
    if ((float)CompareValue > MAX_DUTY * DP_PWM_PER) {
        //BOOST半桥占空比，Dboost = D总 - Dbuck
        boost_duty = MAX_DUTY2 * DP_PWM_PER - (float)CompareValue;
    }
    else {
        //BUCK模式下boost_duty给固定占空比
        boost_duty = MAX_DUTY * DP_PWM_PER;
    }
    //计算buck半桥占空比
    if ((float)CompareValue > MAX_DUTY * DP_PWM_PER) {
        //BOOST模式下buck_duty固定占空比
        buck_duty = MAX_DUTY * DP_PWM_PER;
    }
    else {
        //BUCK半桥占空比
        buck_duty = CompareValue;
    }
    //占空比限制
    if (boost_duty > MAX_PWM_CMP) boost_duty = MAX_PWM_CMP;
    if (boost_duty < MIN_PWM_CMP) boost_duty = MIN_PWM_CMP;
    if (buck_duty > MAX_PWM_CMP) buck_duty = MAX_PWM_CMP;
    if (buck_duty < MIN_PWM_CMP) buck_duty = MIN_PWM_CMP;

    //更新比较寄存器
    setHRTim1_Pwm_outputs(buck_duty, 50, boost_duty);
}



 